namespace :realtime do
  # rake realtime:index
  # 5分钟：len 48/天
  desc "index"
  task index: :environment do
    puts "【realtime:index】#{Time.now}  start"
    abort unless trade_time
    sh_index = RealTime.index "sh000001"
    change = cul_change(sh_index["yes_close"], sh_index["close"])
    open_change = cul_change(sh_index["yes_close"], sh_index["open"])
    content = <<~MD
      ** 上证指数 ***
      > 当前:#{sh_index["close"].to_i}   涨幅:#{change}%
      >      
      > 今开:#{sh_index["open"].to_i}   开盘:#{open_change}% 
    MD
    kline_5min = RealTime.kline "sh000001", 5, 5, 960
    change_5min = cul_change(kline_5min[-2]["low"].to_f, kline_5min[-2]["high"].to_f)
    Robot.send_alert "#{Time.now.strftime("%m-%d %H:%M")} 上证指数震幅超0.18%： #{change_5min}" if change_5min.abs >= 0.18
    kline_5min_day = kline_5min.select { |x| x["day"].split(" ")[1] == kline_5min[-2]["day"].split(" ")[1] }
    cur_5min = kline_5min_day[-1]
    yes_5min = kline_5min_day[-2]
    volume_change_5min = (cur_5min["volume"].to_f / yes_5min["volume"].to_f).round(2)
    content << <<~MD
      > 5m量:#{volume_change_5min}   日量:#{today_volume "sh000001"} 
    MD
    Robot.send_index content
    puts "【realtime:index】#{Time.now}  end"
  end

  # 根据板块  新晋前20板块
  # 根据板块个股推荐
  # rake realtime:block
  desc "block"
  task block: :environment do
    puts "【realtime:block】#{Time.now}  start"
    abort unless trade_time
    hyzjl_top_50 = nok_home "hyzjl"
    hyzjl_top_50.reverse.each do |hy|
      hy.store("mark", "new"); hy.store("cate_type", "I"); hy.delete("id")
      BlockFlow.create(hy)
    end
    hy_bases = BlockFlow.where(created_at: Time.current.beginning_of_day..Time.current.end_of_day, cate_type: "I", mark: "base")
    hy_news = BlockFlow.where(created_at: Time.current.beginning_of_day..Time.current.end_of_day, cate_type: "I", mark: "new")
    hy_bases_20 = hy_bases.last(20) # [重点] [2,1]
    hy_news_20 = hy_bases.last(20) # [重点] [2,1]
    hy_choices = (hy_news_20.pluck(:name) - hy_bases_20.pluck(:name))[0..10]
    hy_choices.each do |name|
      hy_news.find { |hash| hash[:name] == name }.update_attribute("is_choice", true)
      content = <<~MD
        ** 【hy】 (news - bases)***
        > #{name} -- rake ths:block_stock['#{Block.find_by_name(name).ts_code}']
        > 排名：#{hy_news.reverse.find_index { |hash| hash[:name] == name }} 
        > 涨幅：#{hy_news.reverse.find { |hash| hash[:name] == name }.change} 
      MD
      Robot.send_block content
    end
    hy_bases.each { |x| x.update(mark: "old") } unless hy_bases.blank?
    hy_news.each { |x| x.update(mark: "base") }

    gnzjl_top_50 = nok_home "gnzjl"
    gnzjl_top_50.reverse.each do |gn|
      gn.store("mark", "new"); gn.store("cate_type", "N"); gn.delete("id")
      BlockFlow.create(gn)
    end
    gn_bases = BlockFlow.where(created_at: Time.current.beginning_of_day..Time.current.end_of_day, cate_type: "N", mark: "base")
    gn_news = BlockFlow.where(created_at: Time.current.beginning_of_day..Time.current.end_of_day, cate_type: "N", mark: "new")
    gn_bases_20 = gn_bases.last(20)
    gn_news_20 = gn_news.last(20)
    gn_choices = (gn_news_20.pluck(:name) - gn_bases_20.pluck(:name))[0..10]
    gn_choices.each do |name|
      gn_news.find { |hash| hash[:name] == name }.update_attribute("is_choice", true)
      content = <<~MD
        ** 【gn】 (news - bases)***
        > #{name} -- rake ths:block_stock['#{Block.find_by_name(name).ts_code}']
        > 排名：#{gn_news.reverse.find_index { |hash| hash[:name] == name }} 
        > 涨幅：#{gn_news.reverse.find { |hash| hash[:name] == name }.change} 
      MD
      Robot.send_block content
    end
    gn_bases.each { |x| x.update(mark: "old") } unless hy_bases.blank?
    gn_news.each { |x| x.update(mark: "base") }
    puts "【realtime:block】#{Time.now}  end"
  end

  # rake realtime:sina_today_all   # 交易时间每分钟执行一次
  desc "sina_today_all"
  task sina_today_all: :environment do
    puts "【realtime:sina_today_all】#{Time.now}  start"
    RealTime.sina_today_all.each { |stock| $Redis.set(stock["code"], stock.to_json) }
    puts "【realtime:sina_today_all】#{Time.now}  end"
  end

  # rake realtime:limit_ths_flow   # 交易时间每分钟执行一次
  desc "limit_ths_flow"
  task limit_ths_flow: :environment do
    puts "【realtime:limit_ths_flow】#{Time.now}  start"
    time = Time.now
    LimitList.last_pretrade_date.each do |limit|
      (Robot.send_alert "【realtime:limit_ths_flow】ali_ths_flow 超过一分钟"; abort) if Time.now - time > 58
      ali_ths_flow = RealTime.ali_ths_flow limit.ts_code[0..5]
      limit.update(ths_flow: ali_ths_flow["title"]["je"], score: ali_ths_flow["score"])
    end
    # Stock.is_choice?.each do |stock|
    #   (Robot.send_alert "ths_flow 超过一分钟"; abort) if Time.now - time > 58
    #   ths_flow = RealTime.ths_flow stock.symbol
    #   stock.update(ths_flow: ths_flow["title"]["je"], score: ths_flow["score"])
    # end
    puts "【realtime:limit_ths_flow】#{Time.now}  end"
  end

  # rake realtime:buy_point_flow
  desc "buy_point_flow"
  task buy_point_flow: :environment do
    puts "【realtime:buy_point_flow】#{Time.now}  start"
    all_codes = Stock.is_buy_point?.pluck(:symbol)
    all_codes_pool = Stock.is_buy_point?.pluck(:symbol)
    all_codes.each do |batch|
      next if all_codes_pool.exclude? batch

      codes = all_codes_pool[0..58] # 调整每次获取数量
      flows = RealTime.fc_ths_flow(codes.join("-"))
      Robot.send_alert "fc_ths_flow 获取失败，请重新部署函数计算。" if flows.nil?
      puts Time.now
      flows_arr = Array[codes.zip(flows["results"])]

      arr = []
      flows_arr.first.each do |symbol, flow|
        if flow.nil?
          debugger
        end
        Stock.find_by_symbol(symbol).update(ths_flow: flow["title"]["je"])
        arr << symbol
        next if flow["field"].blank?
        flow["field"]["hyzdf"].each do |ths_flow|
          next if Stock.find_by_symbol(ths_flow["stockcode"]).nil?
          Stock.find_by_symbol(ths_flow["stockcode"]).update(ths_flow: ths_flow["je"])
          arr << ths_flow["stockcode"].to_s
        end
        (flow["field"]["desc"] + flow["field"]["asc"]).each do |ths_flow|
          next if Stock.find_by_symbol(ths_flow["stockcode"]).nil?
          Stock.find_by_symbol(ths_flow["stockcode"]).update(ths_flow: ths_flow["ddje"])
          arr << ths_flow["stockcode"].to_s
        end
        all_codes_pool = all_codes_pool - arr
      end
    end
    puts "【realtime:buy_point_flow】#{Time.now}  end"
  end
  # rake realtime:buy_point_volume_score
  desc "buy_point_volume_score"
  task buy_point_volume_score: :environment do
    puts "【realtime:buy_point_volume_score】#{Time.now}  start"
    (puts "非交易日不执行"; abort) if Time.now.strftime("%Y%m%d") != last_trade_date["cal_date"]
    abort unless trade_time
    redis_stocks = Parallel.map(Stock.is_buy_point?, in_processes: 1, progress: false) do |stock|
      JSON.parse $Redis.get(stock.symbol)
    end
    choice = Stock.is_buy_point?.where("ths_flow > 0 AND year_count > 0")
    stock_up1_3 = choice.select { |stock| (redis_stocks.find { |x| x["code"] == stock.symbol }["changepercent"].to_f > 1) && (redis_stocks.find { |x| x["code"] == stock.symbol }["changepercent"].to_f <= 3) }
    stock_up1_3.each do |stock|
      score = Nokogiri::HTML(URI.open("https://stockpage.10jqka.com.cn/#{stock.symbol}/")).css('.analyze-num').text
      volume_change = today_volume(stock.symbol)
      stock.volume_change = volume_change
      stock.score = score
      stock.save
    end
    puts "【realtime:buy_point_volume_score】#{Time.now}  end"
  end

  # rake realtime:block_buy_point[10]
  desc "block_buy_point"
  task :block_buy_point, [:limit] => :environment do |t, args|
    limit = args[:limit].to_i > 0 ? args[:limit].to_i : 10 # 默认值为 10
    puts "【realtime:block_buy_point】#{Time.now}  start, limit: #{limit}"
    gn_base50_name = BlockFlow.where(cate_type: "N", mark: "base").last(limit).pluck(:name)
    hy_bases50_name = BlockFlow.where(cate_type: "I", mark: "base").last(limit).pluck(:name)
    (gn_base50_name + hy_bases50_name).each do |name|
      Block.find_by_name(name).stocks.each do |stock|
        stock_redis = JSON.parse($Redis.get(stock.symbol))
        if stock.is_buy_point? && stock.year_count.to_i > 0 && stock.ths_flow > 0 && stock_redis["per"] > 0 && stock_redis["changepercent"] < 3
          printf_block_buy_point(name, stock, stock_redis)
        end
      end
    end
    puts "【realtime:block_buy_point】#{Time.now}  end"
  end
end

def printf_block_buy_point(name, stock, stock_redis)
  printf("change: %5s per:%4s pb:%3s  市值:%5s 流通:%5s【】 Year_C:%2s  flow: %6s score: %3s Volume_C:%5s %6s %6s 板块: %6s\n",
         stock_redis["changepercent"]&.to_f.round(2), stock_redis["per"].to_i, stock_redis["pb"].to_i, stock_redis["mktcap"].to_i / 10000, stock_redis["nmc"].to_i.to_i / 10000,
         stock.year_count, stock.ths_flow, stock.score, stock.volume_change,
         stock.symbol, stock.name[0..3].ljust(4, padstr = "囗"),
         name + Block.find_by_name(name).cate_type)
end